package shuaige.jdk.stream.collectors相关的方法;

import shuaige.jdk.model.Employee;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

public class GroupingBy {
    public static void main(String[] args) {
        Comparable<Integer> comparable = new Comparable<>() {
            @Override
            public int compareTo(Integer o) {
                return 0;
            }
        };

    }

    public static void 连续分组() {
        // 生成测试数据
        List<Employee> emps = getEmps();
        Map<String, Map<Integer, List<Employee>>> collect = emps.stream().collect(
                // 先按照 city 分组
                Collectors.groupingBy(Employee::getCity,
                        // 再按照 sales 分组
                        Collectors.groupingBy(Employee::getSales)
                ));
        collect.forEach((k, m) -> {
            System.out.println("name：" + k);
            m.forEach((key, value) -> System.out.println("age" + key + " = " + value));
        });
    }

    /**
     * 先按city分组，每个分组里面是一个员工集合
     */
    public static void 一个参数_按照传入的值进行分组并返回数据() {
        List<Employee> emps = getEmps();

        Map<String, List<Employee>> map = emps
                .stream()
                .collect(Collectors.groupingBy(Employee::getCity));

        map.forEach((key, val) -> {
            System.out.println("城市：" + key + " ---员工集： " + val);
        });
    }

    /**
     * 先按city分组 ，再对组里面的成员，统计总销售额
     */
    public static void 二个参数_按照传入的值进行分组_返回数据_再聚合数据() {
        List<Employee> emps = getEmps();
        for (Employee emp : emps) {
            System.out.println(emp);
        }
        // 先按city分组
        // 再对组里面的成员，统计总销售额
        Map<String, Integer> map = emps.stream().
                collect(Collectors.groupingBy(Employee::getCity
                        , Collectors.summingInt(Employee::getSales)));
        map.forEach((key, val) -> {
            System.out.println("城市：" + key + " 销售总额：" + val);
        });
    }

    /**
     * 获取每个城市的姓氏集
     * 先按城市分组，再对每个组里面的员工姓名放入Set，得到每个城市的姓氏集
     */
    public static void 二个参数_按照传入的值进行分组_返回数据_再重新转换数据() {
        List<Employee> emps = getEmps();
        Map<String, Set<String>> map = emps
                .stream()
                .collect(Collectors
                        .groupingBy(Employee::getCity,
                                Collectors.mapping(Employee::getName, Collectors.toSet())));
        map.forEach((key, val) -> {
            System.out.println("" + key + " ---人员姓名： " + val);
        });
    }

    /**
     * 每个城市中销售额最大的员工
     * 先按城市分组，在求分组里面销售额最大的员工
     */
    public static void 二个参数_按照传入的值进行分组_返回数据_再处理问题1() {
        List<Employee> emps = getEmps();
        System.out.println(emps);
        Map<String, Employee> map = emps.stream()
                .collect(Collectors.groupingBy(Employee::getCity,
                        Collectors.collectingAndThen(Collectors
                                        .maxBy(Comparator.comparingInt(Employee::getSales))
                                , Optional::get)));

        map.forEach((key, val) -> {
            System.out.println("城市：" + key + " 销售额最大员工：" + val);
        });
    }

    /**
     * 每个城市中销售额最大的员工
     * 先按城市分组，在求分组里面销售额最大的员工
     */
    public static void 二个参数_按照传入的值进行分组_返回数据_再处理问题2() {
        List<Employee> emps = getEmps();
        System.out.println(emps);
        Map<String, Optional<Employee>> collect = emps.stream()
                .collect(Collectors.groupingBy(Employee::getCity,
                        Collectors.reducing(BinaryOperator
                                .maxBy(Comparator.comparing(Employee::getSales)))));
        collect.forEach((key, val) -> {
            System.out.println("城市：" + key + " 销售额最大员工：" + val);
        });
    }

    /**
     * 3个参数的方法：groupingBy(Function,Supplier,Collector)
     * 要求：要计算每个城市中人的姓氏集，并对城市名称进行排序
     * 先按城市分组，在对每个城市
     */
    public static void 三个参数_按照传入的值进行分组_返回数据_再处理问题() {
        List<Employee> emps = getEmps();
        TreeMap<String, Set<String>> map = emps.stream()
                .collect(Collectors.groupingBy(Employee::getCity,
                        TreeMap::new, Collectors.mapping(Employee::getName, Collectors.toSet())));
        map.forEach((key, val) -> {
            System.out.println("城市：" + key + " 姓氏集：" + val);
        });
    }

    /**
     * 生成测试数据
     */
    private static List<Employee> getEmps() {
        List<Employee> list = new ArrayList<>();
        Random rd = new Random();
        String[] citys = {"北京", "上海", "广州", "杭州", "深圳"};
        String[] firstName = {"张", "李", "杨", "宁", "刘", "王", "高", "葛"};
        Integer[] sales = {100, 50, 30, 20};

        for (int i = 0; i < 10; i++) {
            String city = citys[rd.nextInt(5)];
            Integer sale = sales[rd.nextInt(4)];
            String fname = firstName[rd.nextInt(firstName.length)];

            list.add(new Employee(fname, city, sale));
        }

        return list;
    }

}
